package com.rfid.transport;

import com.rfid.api.GFunction;
import com.rfid.basetype.UINT16;
import com.rfid.basetype.UINT32;
import com.rfid.basetype.UINT8;

import java.nio.ByteBuffer;

public class BufferPack {
    private int m_writePos;

    public BufferPack() {
        this.m_writePos = 0;
        this.m_readPos = 0;
        this.byBuffer = null;
        this.byBuffer = ByteBuffer.allocate(51200);
    }

    public int m_readPos;
    ByteBuffer byBuffer;

    public BufferPack(int maxSize) {
        this.m_writePos = 0;
        this.m_readPos = 0;
        this.byBuffer = null;
        if (maxSize > 0) this.byBuffer = ByteBuffer.allocate(maxSize);
        else this.byBuffer = ByteBuffer.allocate(51200);
    }

    public boolean WriteData(byte data) {
        if (this.m_writePos + 1 > this.byBuffer.capacity()) return false;
        this.byBuffer.put(data);
        this.m_writePos++;
        return true;
    }

    public boolean WriteData(byte[] data, int offset, int len) {
        if (len <= 0) return true;
        if (len + this.m_writePos > this.byBuffer.capacity()) return false;
        if (data == null) {
            data = new byte[len];
            for (int i = 0; i < len; i++) data[i] = 0;
            offset = 0;
        }
        this.byBuffer.put(data, offset, len);
        this.m_writePos += len;
        return true;
    }

    public boolean WriteData(char data) {
        if (this.m_writePos + 2 > this.byBuffer.capacity()) return false;
        data = (char) (data & 0xFFFF);
        this.byBuffer.put((byte) (data & 0xFF));
        this.m_writePos++;
        this.byBuffer.put((byte) (data >> '\b' & 0xFF));
        this.m_writePos++;
        return true;
    }

    public boolean WriteData(int data) {
        if (this.m_writePos + 4 > this.byBuffer.capacity()) return false;
        data &= 0xFFFFFFFF;
        this.byBuffer.put((byte) (data & 0xFF)).put((byte) (data >> 8 & 0xFF)).put((byte) (data >> 16 & 0xFF)).put((byte) (data >> 24 & 0xFF));
        this.m_writePos += 4;
        return true;
    }

    public boolean WriteData(BufferPack data) {
        return WriteData(data.GetBuffer(), 0, data.getBufferLen());
    }
    public  boolean WriteData(String strHex)
    {
        byte[] mWrite=   GFunction.decodeHex(strHex);
        return  WriteData(mWrite,0,mWrite.length);
    }
    public int ReadData(UINT8 val) {
        byte data = this.byBuffer.get(this.m_readPos);
        this.m_readPos++;
        val.setValue(data);
        return 1;
    }

    public byte ReadData() {
        byte data = this.byBuffer.get(this.m_readPos);
        this.m_readPos++;
        return data;
    }

    public int ReadData(UINT16 val) {
        char data = Character.MIN_VALUE;
        char ch1 = (char) ((char) this.byBuffer.get(this.m_readPos) & 0xFF);
        char ch2 = (char) ((char) this.byBuffer.get(this.m_readPos + 1) & 0xFF);
        data = (char) (ch1 | ch2 << '\b');
        this.m_readPos += 2;
        val.setValue(data);
        return 2;
    }

    public int ReadData(UINT32 val) {
        long data = 0L;
        long ch1 = this.byBuffer.get(this.m_readPos) & 0xFFL;
        long ch2 = this.byBuffer.get(this.m_readPos + 1) & 0xFFL;
        long ch3 = this.byBuffer.get(this.m_readPos + 2) & 0xFFL;
        long ch4 = this.byBuffer.get(this.m_readPos + 3) & 0xFFL;
        data = ch1 | ch2 << 8 | ch3 << 16 | ch4 << 32;
        val.setValue(data);
        this.m_readPos += 4;
        return 4;
    }

    public int ReadData(byte[] data, int lenToRead) {
        int byteRead = 0;
        if (lenToRead + this.m_readPos > this.m_writePos)
            byteRead = this.m_writePos - this.m_readPos;
        else byteRead = lenToRead;
        for (int i = 0; i < byteRead; i++) {
            if (data != null) data[i] = this.byBuffer.get(this.m_readPos);
            this.m_readPos++;
        }
        return byteRead;
    }

    public int readable_length() {
        if (this.m_readPos >= this.m_writePos || this.m_readPos < 0) return 0;
        return this.m_writePos - this.m_readPos;
    }

    public void flush() {
        this.byBuffer.clear();
        this.m_writePos = 0;
        this.m_readPos = 0;
    }

    public byte[] GetBuffer() {
        byte[] by = new byte[this.m_writePos];
        for (int i = 0; i < by.length; i++) by[i] = this.byBuffer.get(i);
        return by;
    }

    public byte[] GetReadtableBuffer() {
        int curLen = readable_length();
        if (curLen <= 0) return new byte[0];
        byte[] mBuffer = new byte[curLen];
        for (int i = 0; i < mBuffer.length; i++) mBuffer[i] = this.byBuffer.get(this.m_readPos + i);
        return mBuffer;
    }


    public int getBufferLen() {
        return this.m_writePos;
    }
}
